package cn.xuqiudong.sso.server.config;

import cn.xuqiudong.sso.server.model.AppClient;
import cn.xuqiudong.sso.server.service.ClientConfigService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 描述:
 *      sso server端的一些配置
 * @author Vic.xu
 * @since 2021-11-02 17:12
 */
@Configuration
@ConfigurationProperties(prefix = "sso")
public class SsoConfiguration {

    /**
     * 超时时间：默认2个小时 <br />
     * <p>
     *  包括：登录凭证TicketGrantingTicket(tgt)；
     *  刷新凭证 RefreshToken；
     *
     *</p>
     */
    @Value("${sso.timeout:7200}")
    private int timeout;

    /**
     * 授权码超时时间 默认10分钟
     */
    @Value("${sso.codeTimeout:600}")
    private int codeTimeout;

    /**
     * accessToken 的超时时间 默认为timeout的一半
     */
    private int accessTokenTimeout;

    /**
     * 存储策略，只支持redis和local
     */
    @Value("${sso.storageStrategy:local}")
    private String storageStrategy;

    /**
     * 配置文件排位置的sso client 列表
     */
    private List<AppClient> clients;

    /**
     * key: appId ;
     * value : AppClient
     * 每5分钟会同步
     * @see ClientConfigService#updateClientsConfigSchedule()
     */
    public Map<String, AppClient> clientMap;

    public SsoConfiguration() {
        this.clients = new ArrayList<>();
        this.clientMap = new ConcurrentHashMap<>();
    }

    @PostConstruct
    private void post() {
        if (accessTokenTimeout == 0) {
            accessTokenTimeout = timeout / 2;
        }
        if (accessTokenTimeout >= timeout) {
            throw new IllegalStateException("accessTokenTimeout必须小于timeout， 否则不能及时刷新更换token");
        }
        clientMap.putAll(clients.stream().collect(Collectors.toMap(AppClient::getId, c -> c)));


    }


    /**
     * 获取某个appId对应的退出地址
     * @param appId appId
     * @return tLogoutUrl
     */
    public String getLogoutUrl(String appId) {
        return clients.stream().filter(c -> StringUtils.equals(c.getId(), appId)).findFirst().orElse(new AppClient()).getLogoutUrl();
    }

    @Override
    public String toString() {
        return "SsoConfiguration{" +
                "timeout=" + timeout +
                ", codeTimeout=" + codeTimeout +
                ", accessTokenTimeout=" + accessTokenTimeout +
                ", storageStrategy='" + storageStrategy + '\'' +
                ", clients=" + clients +
                '}';
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public int getCodeTimeout() {
        return codeTimeout;
    }

    public void setCodeTimeout(int codeTimeout) {
        this.codeTimeout = codeTimeout;
    }

    public int getAccessTokenTimeout() {
        return accessTokenTimeout;
    }

    public void setAccessTokenTimeout(int accessTokenTimeout) {
        this.accessTokenTimeout = accessTokenTimeout;
    }

    public String getStorageStrategy() {
        return storageStrategy;
    }

    public void setStorageStrategy(String storageStrategy) {
        this.storageStrategy = storageStrategy;
    }

    public List<AppClient> getClients() {
        return clients;
    }

    public void setClients(List<AppClient> clients) {
        this.clients = clients;
    }

    public Map<String, AppClient> getClientMap() {
        return clientMap;
    }

    public void setClientMap(Map<String, AppClient> clientMap) {
        this.clientMap = clientMap;
    }
}
